package la.iok.hzsvn.lewin.movie.operation.service;

import com.wechat.pay.contrib.apache.httpclient.auth.PrivateKeySigner;
import com.wechat.pay.contrib.apache.httpclient.auth.WechatPay2Credentials;
import com.wechat.pay.contrib.apache.httpclient.cert.CertificatesManager;
import com.wechat.pay.contrib.apache.httpclient.exception.HttpCodeException;
import com.wechat.pay.contrib.apache.httpclient.exception.NotFoundException;
import com.wechat.pay.contrib.apache.httpclient.util.PemUtil;
import la.iok.hzsvn.lewin.movie.core.exception.ErrorCode;
import la.iok.hzsvn.lewin.movie.operation.cfg.ServerGatewayProperty;
import la.iok.hzsvn.share.annotations.NotNull;
import la.iok.hzsvn.share.utils.StringUtils;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;

@Service
public class WxConfigBean implements InitializingBean {
    private static final Logger logger = LoggerFactory.getLogger(WxConfigBean.class);
    private static final String AppId = "ww6ff8c54e09d2c9cd";
    /** 商户号 */
    private static final String merchantId = "1618977158";
    /** 商户证书序列号 */
    private static final String merchantSerialNumber = "35D0C1BBF46BE02A6AA5A5483D7477E3E5E5C669";
    /** 微信支付 APIv3 密钥 */
    private static final String apiV3Key = "Vigv0808080808080808080808080808";
    private static final String privateKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3Su9lIS4gmBAY\n" +
            "uYqSUBcIgIkEwwZWYGA4mIfI3zcePNk5g+no0EMqZY7bRWEVvLFFBXmEexNn8its\n" +
            "QvwSJd6hw/KgcrN9PP9YwmPdh+gnZzf7R/IijoSOe8q1brvAic4ANS5eGIEYDzvD\n" +
            "viUDjlXbEB66ZYrPL5x5t3gKisqmbm349OeINzHVHDax4g/+2bbN444aGWX4EOq9\n" +
            "kG2NvSZq2MPwvFvQoO2Y7vlfIdTx3wf/CjU2pI7MLQ4yqXy1hk5wuhTzm+vXFtuz\n" +
            "zcKH1NmXiuvnm9mplU2ianDbb3kBjE59JOPkgj2mcRlUu5WD9GuV5Hnq1ATHMTPM\n" +
            "Fl3QeGjFAgMBAAECggEALv0d7B4adi6licEfHi08CmjxN3BL0p74a+nmfX+D4NOW\n" +
            "mKERuSaS4W6RtfLOVcU+6MPjiCwJKI+zxBhUCM7+iRfzvmBJVWTqzTVgZq1tvZQ/\n" +
            "jMK/903z+5cOu3580XpCflkj3umHRsS4/JBlasj1h6hVSFG5yS2afrWjJ4i3NP0Q\n" +
            "hfBqOKuReYWPYqbNlMFbaaurkEISLG2ITGSvxs+S2Py1DmsoT6RDCLtHuzk6qjh8\n" +
            "RIQFhTZnXVKgijI36lpx5AvTa5zfxHuTctE68KTX9m6VudC79p73r++uTwU5mGF+\n" +
            "VseFmEsh38GaR8eu0+0t0LKfn3tKU3cWXaDmRVC4AQKBgQD0JPYnALgzRDBwZfD4\n" +
            "/OuWxoxCQZWBAgbbxWYGl6gkz4zUi/jK7JlOkZJ+NRmwBu4TgJWhhZJoA+1msabg\n" +
            "F489Jp8RdqzzE0hmI+rHLcNwjj2rY9d3HIMeGEGApD4hUmPLXSy8ZyAN4haSz1+b\n" +
            "8LXxv7HyAPDDF0vaVSq0TbGixQKBgQDAMYG2l+T9bAQYNWNJ/3ZzHdw8t2FA8L3B\n" +
            "OvseXRxPYkktMZgdF1cDC7bcbkO5KzG0pm7wSNWe3uQoNxVCqcie8S+ECZlFoYxM\n" +
            "5zspxCcRfpbcR0S7LizFGBqclU4CcCqWtzslfxwIMp4tk1zhP1FIVT0GQj/fA8ka\n" +
            "MFZ92mAOAQKBgGYreZ+E25EIvkSrRJbOMUEdweCQVaJxWLFsAHBN0x3khYkFMo6p\n" +
            "SNbqcKXETwWtQMCElRnNLiG9UwIg4jbxZQ4wNW03ftUSgr/L1BqaeimGPSSWWbsN\n" +
            "AYn8mJzfHukO85hNW8VUWsO0k8HIarh1mY6brDocTqU2AJZUAdUGlooJAoGAGoW6\n" +
            "dMw5WY+ScRTNAuUyH2i7f9V+okuWpBfTl7kZswrJNmdlqn4SD+WJ8pl01xTS4y8k\n" +
            "mBw0/pubuMEBOhXcDbMS75GziRxmFCbEz1q2WX+yqetb3MjefMR6x6kC/usjtXDL\n" +
            "xLzpzWfO1FNFuf/W47h/l2GFFu2azvZkuTFtmAECgYEAplHDQReqOwuXmG7EXtqz\n" +
            "NqcsdGVQ9ntD7A4bz6mTxRg9/T/Pz7OEwByhx+YKG3YuIiV4H0B9g4s4PVB0DJVr\n" +
            "uqh3uqdQtmfv0HpMSNrrnBUUMKg66L1gDZmFWyTX8viWJWVDk6froYTUGHA05su5\n" +
            "8URI680rpeH6+ZlyECnxbg0=";
    @Value("${server.servlet.context-path:}")
    private String defaultContextPath;
    private final ServerGatewayProperty serverGatewayProperty;

    public WxConfigBean(ServerGatewayProperty serverGatewayProperty) {
        this.serverGatewayProperty = serverGatewayProperty;
    }

    @PostConstruct
    public void init(){
        PrivateKey merchantPrivateKey = PemUtil.loadPrivateKey(privateKey);
        // 获取证书管理器实例
        CertificatesManager certificatesManager = CertificatesManager.getInstance();
        // 向证书管理器增加需要自动更新平台证书的商户信息
        try {
            certificatesManager.putMerchant(merchantId, new WechatPay2Credentials(merchantId,
                    new PrivateKeySigner(merchantSerialNumber, merchantPrivateKey)), apiV3Key.getBytes(StandardCharsets.UTF_8));
        } catch (IOException | GeneralSecurityException | HttpCodeException e) {
            throw new RuntimeException("微信证书更新失败");
        }
    }

    public String appId(){
        return AppId;
    }

    public String merchantId(){
        return merchantId;
    }

    public String apiKey(){
        return apiV3Key;
    }

    public String privateKey(){
        return privateKey;
    }

    public String merchantSerialNumber(){
        return merchantSerialNumber;
    }

    @Nullable
    public X509Certificate getX509Certificate() {
        CertificatesManager manager = CertificatesManager.getInstance();
        int times = 3;
        X509Certificate certificate = null;
        while (times > 0 && certificate == null){
            try {
                certificate = manager.getVerifier(merchantId()).getValidCertificate();
            } catch (NotFoundException e) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException interruptedException) {
                    interruptedException.printStackTrace();
                }
                times--;
            }
        }
        ErrorCode.WX_CERTIFICATE_NOT_FOUND.assertNotNull(certificate);
        return certificate;
    }

    public String notifyUrl(@NotNull String path){
        return String.format("%s://%s%s%s",serverGatewayProperty.getScheme(),serverGatewayProperty.hostPort(),
                StringUtils.defaultIfBlank(serverGatewayProperty.getContextPath(),defaultContextPath),path);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        logger.info("notifyUrl:" + notifyUrl("/operation/wx/notify"));
    }
}
